主要内容
CSRF一直是OWASP漏洞中的top10之一,分为login CSRF和authenticated CSRF,本篇论文的研究对象则是关注后者authenticated CSRF,简称aCSRF。在aCSRF中,攻击者已经通过了目标网站的身份验证,攻击者可以在HTML页面中嵌入一些恶意的代码。比用户A已经登陆了站点B,并且访问某个页面,而该页面被攻击者插入了恶意代码。当用户A访问该恶意页面时,用户A的浏览器就会发起一个跨域请求,用户A会访问攻击者事先准备好的站点,然后攻击者将用户重定向到修改密码的页面,该请求中会包含用户的session或是cookie等敏感信息,可以让受害者在不知情的情况下修改自己的密码。
当前对于CSRF的自动化漏洞挖掘比较困难,而作者通过建立完善的标签属性图解决了这个难题,设计并实现了工具Deemon,项目地址为: https://github.com/tgianko/deemon 。
实验挑战
作者在解决自动化挖掘CSRF漏洞的问题时主要遇到了两个挑战,detection challenges和operational challenges。
1. Detection Challenge
检测aCSRF需要对应用程序的状态、请求参数的角色role和状态以及观察到的状态转换序列之间的关系进行推理。
(C1) State Transitions
第一个需要解决的问题是确定服务端的状态在什么时候发生了改变,比如用户浏览商品的页面不会引起server-side的状态变化,但是用户改变密码的请求就一定会造成服务器端的状态发生变化,数据库中的信息需要更新:
目前绝大部分的web扫描工具都是采用黑盒的检测方式,只能从服务器端返回的response检测漏洞,经常用在检测xss和sqli漏洞上。所以此类工具并不适用与aCSRF检测,因为aCSRF依赖于server-side的状态转变。
(C2) Security-Relevant State Changes
第2个需要解决的detection难题是,并不是所有的状态改变都是和security相关的。比如一个在线商城可能为了获取商品的流行度,在用户浏览之后,会将商品的浏览次数+1,这也会导致server-side有一个状态的改变:
我们人很容易能够区分这些差别,但是对于工具来说区分这些很难。
(C3) Relationships of Request Parameters and State Transitions
另一个需要解决的detection难题是确定请求参数和状态转换之间的关系。比如一个请求参数为token,那么这个参数就非常有可能是一个随机数,用户想要自己构造是不可能的:
但是如果是一个用户的输入,比如username或是password,那么就有可能会引起用户的账号密码被攻击者篡改。这种情况下是有可能引起server-side的状态变化。
2. Operational Challenge
(C4) Transitions in Non-Trivial Application Workflows
第4个challenge是如何在发起能够使复杂的应用程序状态改变的请求,或者说,如何在复杂的web应用程序工作流中找到导致状态变化的请求。
(C5) Side-Effect-Free Testing
第5个需要解决的问题是如何进行对后续测试没有影响的测试实验。比如有一个在线商城,购物车中的商品被提交之后,后面再向对购物车进行测试就麻烦了,因为购物车已经被清空了。
(C6) Comprehensive, Reusable Representation of Application Functionality
为了检测与security有关的状态改变,其实需要对应用程序进行建模,但是如何对程序建立一个全面的、可重用的应用程序功能表示模型是一个难题。
设计与实现
作者实现了一个名为Deemon的工具来解决上述的几个Challenge。
解决方法
Challenge C1 & C3
对于C1和C3,从程序执行观察中推断出状态转换和数据流信息的模型。对于C3,要确定请求参数和状态转换之间的关系,这个问题使用数据流模型(Data Flow Model,DFM)来解决,作者将HTTP的请求参数分为两种,一种是随机的,是用户不可猜测的,另一种是用户可以猜测的,就认为它是user input。DFM将状态表示为一组变量,并可以捕获数据项从HTTP请求到SQL查询的传播路径。
Challenge C2
利用图遍历的方式对属性图进行一种programmatic的访问,以此确定与安全相关的状态转移。
Challenge C4
增强了Web应用程序的执行环境,主要是通过向应用程序容器插入一些sensor,来跟踪服务器端程序执行和数据库操作顺序等。
Challenge C5
依靠虚拟化环境来测试web应用程序, 通过获取和恢复快照来完全控制Web应用程序。
Challenge C6
使用属性图来表示模型,属性图是一种统一和可重复使用的模型表达方式,且可以通过标记边的方式来定义模型间的精确关系。
工作流程
Deemon的输入有两个:(1)a set of user actions;(2)an application container of the web application under test,是一个runtime环境,包括程序本身、程序运行所需要的依赖和一些相关配置。
Deemon挖掘aCSRF的步骤可以分为两大阶段:
- _instrumentation_,在这一阶段,Deemon会通过安装一些sensor来记录网络的trace、服务器端的程序执行trace和一些数据库的操作等,比如对于PHP应用程序,可以用Xdebug来追踪程序的执行流程,用HTTP代理来拦截server和browser之间的请求。
- _detection_,在第二阶段,Deemon会自动重新生成用户操作,并且根据这些跟踪后得到的trace来推断模型,然后以此探测Web应用程序中的aCSRF漏洞。具体流程如下图所示:
(a)重放用户输入;
(b)在instrumentation阶段安装的sensor产生执行跟踪trace,其中包括网络跟踪(network trace)和函数调用跟踪(function call trace),在这一步Deemon会运行两次,以观察诸如生成伪随机数据项等不确定性数据的来源;
(c)从上一步的这些trace中,Deemon会先生成一个简单的模型(有限状态机和数据流模型)的组合模型,称其为属性图;
(d)Deemon使用该模型来挖掘潜在的漏洞(security test)和一个oracle(出度等于1的SQL查询的抽象分析树根的集合,用于确定是否发生了与安全有关的状态转换);
(e)在web程序中运行找到的security test;
(f)根据oracle预测测试结果来检测aCSRF漏洞。
最后,Deemon会返回一个vulnerability report,其中会列出造成aCSRF的HTTP请求序列。
标签属性图概念
作者在文中提出了标签属性图(Labeled Property Graph,简称LPG)的概念。标签属性图是边和节点都带有标签的有向图,下图是一个简单的LPG图:
节点属性:节点n1和n3都有一个属性,n1是k1: v1
,n3是k2: v2
。
节点标签:节点有一个标签,n1、n2和n3的标签分别为L'
,L'
和L''
。
边标签:边也存在标签,e1和e2的标签都为R'
,e3的标签为R''
。
为了构建完整的属性图,需要将sensor跟踪到的trace、FSM和DFM都映射到属性图中。
- Traces and Parser Trees
trace是sensor记录下来的比如HTTP请求或是SQL查询之类的信息。在属性图中,一个节点表示一个Event,每个Event之间用边连接起来,边会有一个标签next,表示Event之间生成的前后关系。
下图是更新用户密码对应的属性图(为了可读性,其中不包括用户操作):
比如在上图3.d中,e'
表示一个HTTP请求:
Deemon会解析HTTP请求,并将得到的解析树存储在属性图中,一个解析树中不包括Host,Content-Type和Content-Length等无用的HTTP请求头信息。解析树的节点有三种node lable:
- Root,解析树的父节点;
- NTerm,该节点有后继节点;
- Term,该节点没有后继节点。
节点之间用child边标签连接。
- Finite State Machines
为了对HTTP请求引起的程序状态之间的转变进行建模,作者使用有限状态机来解决这个问题,因为目前的模型中,HTTP请求被表示为一个节点,但是属性图不支持在节点(例如HTTP请求)和边(例如转换)之间构建一条关系边。所以,作者将两个状态之间的转变堪称一个整体,作为一个node,这个node有三条边:
- 第一条边是和HTTP请求节点之间的边;
- 第二条边是从上一个状态到当前状态的边;
- 第三条边是到下一个新的状态的边。
- Dataflow Information and Types
作者使用DFMs来描述HTTP请求参数和状态转变之间的关系,对某个变量进行建模。比如一个HTTP请求有参数password=pwnd
,该参数是一个node,node中会记录参数名和参数值,以及参数的标签,syn_type和sem_type,syn_type是句法类型,表示该参数的类型,如string或int;sem_type是语义类型,如UG表示user-generated,SU表示user session。
DFM的节点和FSM的节点之间通过has边联系起来,表示请求参数和状态改变之间的关系。
实验评估
Deemon对10种Web应用程序进行了测试:
Deemon会首先通过user action捕获数据流,主要分为3种类型:
- 仅收集新的执行流程,不追踪用户;
- 对执行流程和用户同时进行追踪;
- 执行相同的执行流程但是更换用户角色。
对于每个应用程序,Deemon大概需要13m的时间输出最后的结果,结果如下图所示,第3列表示生成trace的时间,第4列表示建模的时间,最后一列表示测试的时间:
在下图中,Reqs表示所有的请求数量,SC Reqs表示引起状态变化的请求,Rel. SC Reqs表示与安全相关的状态改变的请求。从结果中知道,几乎所有的请求都会引起程序状态的改变,但是和security相关的又不多。
为了防止应用程序受到CSRF的攻击,开发者会对一些功能做anti-CSRF的措施,下图可以看到有CSRF防护和没有CSRF防护的攻击效果,显然前者存在的漏洞更少,但是即使进行了anti-CSRF,仍然可能会存在CSRF漏洞。
总结
本篇论文主要的贡献在于:
- 设计并实现了Deemon来挖掘web应用程序中的aCSRF漏洞;
- Deemon的核心就是使用属性图来建模;
- 利用Deemon对10个应用程序进行了测试,发现了14个CSRF漏洞。